package io.gitee.zhangbinhub.admin.component

import cn.dev33.satoken.stp.StpUtil
import com.mybatisflex.core.query.QueryWrapper
import io.gitee.zhangbinhub.admin.constant.WorkFlowConstant
import io.gitee.zhangbinhub.admin.entity.User
import io.gitee.zhangbinhub.admin.entity.UserOrg
import io.gitee.zhangbinhub.admin.entity.UserRole
import io.gitee.zhangbinhub.admin.repo.UserOrgRepository
import io.gitee.zhangbinhub.admin.repo.UserRepository
import io.gitee.zhangbinhub.admin.repo.UserRoleRepository
import org.dromara.warm.flow.core.handler.PermissionHandler
import org.noear.solon.annotation.Component

@Component
class WorkFlowPermissionHandler(
    private val userRepository: UserRepository,
    private val userRoleRepository: UserRoleRepository,
    private val userOrgRepository: UserOrgRepository
) : PermissionHandler {
    fun userIdList(permissionList: List<String>): Set<String> = permissionList.map { permission ->
        when {
            permission.startsWith(WorkFlowConstant.PERMISSION_ROLE_PREFIX) -> {
                permission.substring(WorkFlowConstant.PERMISSION_ROLE_PREFIX.length).let { roleId ->
                    userRoleRepository.selectListByQuery(
                        QueryWrapper.create().where(UserRole::roleId).eq(roleId)
                    ).map { it.userId }
                }
            }

            permission.startsWith(WorkFlowConstant.PERMISSION_DEPT_PREFIX) -> {
                permission.substring(WorkFlowConstant.PERMISSION_DEPT_PREFIX.length).let { organizationId ->
                    userOrgRepository.selectListByQuery(
                        QueryWrapper.create().where(UserOrg::organizationId).eq(organizationId)
                    ).map { it.userId }
                }
            }

            else -> listOf(permission.trim())
        }
    }.flatten().toSet()

    fun permissions(userIdList: List<String>): Set<String> = userIdList.mapNotNull { userId ->
        userRepository.selectOneWithRelationsById(userId)?.let { user ->
            mutableListOf<String>().apply {
                this.add(user.id)
                user.roleSet.forEach { role ->
                    this.add("${WorkFlowConstant.PERMISSION_ROLE_PREFIX}${role.id}")
                }
                user.organizationSet.forEach { organization ->
                    this.add("${WorkFlowConstant.PERMISSION_DEPT_PREFIX}${organization.id}")
                }
            }
        }
    }.flatten().toSet()

    override fun permissions(): MutableList<String> = mutableListOf<String>().apply {
        userRepository.selectOneByQuery(
            QueryWrapper.create().where(User::loginNo).eq(StpUtil.getLoginIdAsString())
        )?.let { user ->
            permissions(listOf(user.id))
        }
    }

    override fun getHandler(): String? = userRepository.selectOneByQuery(
        QueryWrapper.create().where(User::loginNo).eq(StpUtil.getLoginIdAsString())
    )?.id
}